home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1996 March / EnigmA AMIGA RUN 05 (1996)(G.R. Edizioni)(IT)[!][issue 1996-03][Skylink CD IV].iso / earcd / dtype / txtdtpch.lha / textdtpatch / textdtpatch.c < prev    next >
C/C++ Source or Header  |  1995-07-04  |  13KB  |  555 lines

  1. /*
  2. ** $PROJECT: text.datatype patch
  3. **
  4. ** $VER: textdtpatch.c 39.1 (04.07.95)
  5. **
  6. ** by
  7. **
  8. ** Stefan Ruppert , Windthorststraße 5 , 65439 Flörsheim , GERMANY
  9. **
  10. ** (C) Copyright 1995
  11. ** All Rights Reserved !
  12. **
  13. ** $HISTORY:
  14. **
  15. ** 04.07.95 : 039.001 : initial
  16. */
  17.  
  18. /* ----------------------------- version data ----------------------------- */
  19.  
  20. /*FS*/ /* $STARTDEFINE: "BumpRev defines"*/
  21. #define VERSION  39
  22. #define REVISION 1
  23. #define DATE "3.7.95"
  24. #define VERS "textdtpatch 39.1"
  25. #define VSTRING "textdtpatch 39.1 (3.7.95)\r\n"
  26. #define VERSTAG "\0$VER: textdtpatch 39.1 (3.7.95)"
  27. /*FE*/ /* $ENDDEFINE:   */
  28.  
  29. /* ------------------------------- autodoc -------------------------------- */
  30.  
  31. /*FS*/ /*"AutoDoc"*/
  32. /*GB*** textdtpatch **********************************************************
  33. *
  34. *    NAME
  35. *        textdtpatch - patches the text.datatype to support search method
  36. *
  37. *    TEMPLATE
  38. *        none
  39. *
  40. *    REQUIREMENT
  41. *        reqtools.library V38, OS3.0 or higher
  42. *
  43. *    FUNCTION
  44. *        This program patches the text.datatype, so that the new one can
  45. *        search for a string. The following key commands are supported :
  46. *
  47. *        Return (STM_ACTIVATE_FIELD) - opens a reqtools requester to enter
  48. *            the search string and searches for that if confirmed.
  49. *
  50. *        Tab (STM_NEXT_FIELD) , '>' (STM_BROWSE_NEXT) searches for the next
  51. *            occurrence of the string.
  52. *
  53. *        Shift-Tab (STM_PREV_FIELD) , '<' (STM_BROWSE_PREV) searches for the
  54. *            previous occurrence of the string.
  55. *
  56. *    INSTALLATION
  57. *        1. Copy textdtpatch to your c: or anywhere you like.
  58. *        2. Add in your S:User-Startup following line:
  59. *           run >nil: c:textdtpatch
  60. *        3. To terminate textdtpatch send a break (Ctrl-C).
  61. *
  62. *    SEE ALSO
  63. *        text.datatype
  64. *
  65. *    AUTHOR
  66. *        Stefan Ruppert
  67. *        Windthorststrasse 5
  68. *        65439 Floersheim Main
  69. *        GERMANY
  70. *        EMail: ruppert@vs3.informatik.fh-wiesbaden.de
  71. *
  72. *****************************************************************************/
  73. /*FE*/
  74.  
  75. /* ------------------------------- include -------------------------------- */
  76.  
  77. #include <exec/types.h>
  78. #include <exec/memory.h>
  79.  
  80. #include <clib/alib_protos.h>
  81. #include <clib/datatypes_protos.h>
  82. #include <clib/dos_protos.h>
  83. #include <clib/dtclass_protos.h>
  84. #include <clib/exec_protos.h>
  85. #include <clib/intuition_protos.h>
  86.  
  87. #include <pragmas/datatypes_pragmas.h>
  88. #include <pragmas/dos_pragmas.h>
  89. #include <pragmas/dtclass_pragmas.h>
  90. #include <pragmas/exec_sysbase_pragmas.h>
  91. #include <pragmas/intuition_pragmas.h>
  92.  
  93. #include <dos/dostags.h>
  94. #include <datatypes/textclass.h>
  95.  
  96. #include <clib/reqtools_protos.h>
  97. #include <pragmas/reqtools.h>
  98. #include <libraries/reqtools.h>
  99.  
  100. #include <string.h>
  101.  
  102. /* ------------------------- register defintions -------------------------- */
  103.  
  104. #define RegCall      __asm
  105. #define GetA4        __saveds
  106.  
  107. #define REGA0        register __a0
  108. #define REGA1        register __a1
  109. #define REGA2        register __a2
  110.  
  111. /* -------------------------- debug definitions --------------------------- */
  112.  
  113. #ifdef DEBUG
  114. #define bug      kprintf
  115. extern void bug(char *fmt,...);
  116.  
  117. #define D(x)     x
  118. #define DB(x)   { bug(__FILE__ "(%4ld):" __FUNC__ "() :",__LINE__); \
  119.                         bug x; \
  120.                      }
  121. #else
  122. #define bug
  123. #define D(x)
  124. #define DB(x)
  125. #endif
  126.  
  127. /* -------------------------- static data items --------------------------- */
  128.  
  129. static const STRPTR version = VERSTAG;
  130. static const STRPTR prgname = "textdtpatch";
  131.  
  132. /* ------------------------------ prototypes ------------------------------ */
  133.  
  134. RegCall GetA4 ULONG mytextdtdispatcher(REGA0 Class *cl,REGA2 Object *obj,REGA1 Msg msg);
  135. ULONG DoAsyncMethod(Class *cl,Object *obj,Msg msg,ULONG tag1,...);
  136. ULONG DoAsyncMethodA(Class *cl,Object *obj,Msg msg,struct TagItem *tagList);
  137. ULONG NotifyAttrs(Object * obj, void * ginfo, ULONG flags, ULONG tag1,...);
  138.  
  139. ULONG getstring(Class *cl,Object *obj,struct dttGetString *msg);
  140. LONG strseg(struct Line *line,STRPTR str,LONG slen);
  141. ULONG searchstring(Class *cl,Object *obj,LONG direction,struct dttSearchText *msg);
  142.  
  143. /* ------------------------- template definition -------------------------- */
  144.  
  145. #define TRG(msg)           ((struct dtTrigger *) (msg))
  146. #define SM(msg)            ((struct dttGetString *) (msg))
  147.  
  148. #define DTTM_GETSTRING     0x20000
  149. #define DTTM_SEARCHNEXT    0x20001
  150. #define DTTM_SEARCHPREV    0x20002
  151.  
  152. struct ClassData
  153. {
  154.     struct Library *cd_SysBase;
  155.     struct Library *cd_DOSBase;
  156.     struct Library *cd_IntuitionBase;
  157. #if 0
  158.     struct Library *cd_DataTypesBase;
  159. #endif
  160. };
  161.  
  162.  
  163. struct dttGetString
  164. {
  165.     ULONG MethodID;
  166.     struct GadgetInfo dttgs_GInfo;
  167.     LONG dttgs_SearchMethod;
  168. };
  169.  
  170. struct dttSearchText
  171. {
  172.     ULONG MethodID;
  173.     struct GadgetInfo *dttst_GInfo;
  174.     STRPTR dttst_Text;
  175.     LONG dttst_TextLen;
  176. };
  177.  
  178. struct MyTextDTData
  179. {
  180.     UBYTE Buffer[100];
  181.     LONG FoundLine;
  182.     struct dttGetString Msg;
  183. };
  184.  
  185. #define IntuitionBase      cd->cd_IntuitionBase
  186. #define DOSBase            cd->cd_DOSBase
  187. #define DataTypesBase      cd->cd_DataTypesBase
  188.  
  189. /* --------------------------- main entry point --------------------------- */
  190.  
  191. GetA4 int main(void)
  192. {
  193.     struct Library *SysBase = *((struct Library **) 4L);
  194.     struct ClassData *cd;
  195.  
  196.     if(SysBase->lib_Version < 39)
  197.         return(RETURN_FAIL);
  198.  
  199.     if((cd = AllocVec(sizeof(struct ClassData), MEMF_CLEAR | MEMF_ANY)))
  200.     {
  201.         struct Library *DTClassBase;
  202.  
  203.         cd->cd_SysBase = SysBase;
  204.  
  205.         DOSBase       = OpenLibrary("dos.library",39);
  206.         IntuitionBase = OpenLibrary("intuition.library",39);
  207.  
  208.         if((DTClassBase = OpenLibrary("datatypes/text.datatype",39)))
  209.         {
  210.             struct IClass *TextDTClass;
  211.  
  212.             if((TextDTClass = ObtainEngine()))
  213.             {
  214.                 struct IClass *MyTextDTClass;
  215.                 ClassID oldclassid;
  216.  
  217.                 oldclassid = TextDTClass->cl_ID;
  218.                 TextDTClass->cl_ID = "org_text.datatype";
  219.  
  220.                 if((MyTextDTClass = MakeClass("text.datatype",NULL,TextDTClass,sizeof(struct MyTextDTData),0)))
  221.                 {
  222.                     MyTextDTClass->cl_Dispatcher.h_Entry = (HOOKFUNC) mytextdtdispatcher;
  223.                     MyTextDTClass->cl_UserData = (ULONG) cd;
  224.  
  225.                     AddClass(MyTextDTClass);
  226.  
  227.                     Wait(SIGBREAKF_CTRL_C);
  228.  
  229.                     RemoveClass(MyTextDTClass);
  230.  
  231.                     while(!FreeClass(MyTextDTClass))
  232.                         Delay(50);
  233.  
  234.                 } else
  235.                     Printf("can't make new text.datatype class !\n");
  236.  
  237.                 TextDTClass->cl_ID = oldclassid;
  238.  
  239.             } else
  240.                 Printf("can't obtain old text.datatype class !\n");
  241.  
  242.             CloseLibrary(DTClassBase);
  243.         } else
  244.             Printf("can't open text.datatype !\n");
  245.  
  246.         CloseLibrary(IntuitionBase);
  247.         CloseLibrary(DOSBase);
  248.  
  249.         FreeVec(cd);
  250.     }
  251.  
  252.     return(RETURN_OK);
  253. }
  254.  
  255. /*FS*/ ULONG DoAsyncMethod(Class *cl,Object *obj,Msg msg,ULONG tag1,...)
  256. {
  257.     return(DoAsyncMethodA(cl,obj,msg,(struct TagItem *) &tag1));
  258. }
  259. /*FE*/
  260. /*FS*/ /*"ULONG DoAsyncMethodA(Class *cl,Object *obj,Msg msg,struct TagItem *tagList)"*/
  261.  
  262. struct AsyncMethodMsg
  263. {
  264.     struct Message amm_ExecMessage;
  265.     Object *amm_Object;
  266.     Msg amm_Msg;
  267. };
  268.  
  269. RegCall GetA4 ULONG asyncmethodfunc(void)
  270. {
  271.     struct Library *SysBase = *((struct Library **) 4L);
  272.     struct Process *proc = (struct Process *) FindTask(NULL);
  273.     Object *obj;
  274.     Msg msg;
  275.     struct AsyncMethodMsg *amsg;
  276.  
  277.     WaitPort(&proc->pr_MsgPort);
  278.     amsg = (struct AsyncMethodMsg *) GetMsg(&proc->pr_MsgPort);
  279.     obj = amsg->amm_Object;
  280.     msg = amsg->amm_Msg;
  281.     ReplyMsg(&amsg->amm_ExecMessage);
  282.  
  283.     D(bug("recieved object : %lx, msg : %lx\n",obj,msg));
  284.  
  285.     return(DoMethodA(obj,msg));
  286. }
  287.  
  288. #define SysBase         cd->cd_SysBase
  289.  
  290. ULONG DoAsyncMethodA(Class *cl,Object *obj,Msg msg,struct TagItem *tagList)
  291. {
  292.     struct ClassData *cd = (struct ClassData *) cl->cl_UserData;
  293.     struct AsyncMethodMsg amsg;
  294.     struct Process *proc = NULL;
  295.     struct MsgPort *mport;
  296.  
  297.     DB(("before CreateMsgPort() !\n"));
  298.  
  299.     if((mport = CreateMsgPort()))
  300.     {
  301.  
  302.         DB(("after CreateMsgPort() !\n"));
  303.  
  304.         amsg.amm_Object = obj;
  305.         amsg.amm_Msg    = msg;
  306.  
  307.         amsg.amm_ExecMessage.mn_Node.ln_Type = NT_MESSAGE;
  308.         amsg.amm_ExecMessage.mn_ReplyPort    = mport;
  309.  
  310.         DB(("before CreateNewProcTags() !\n"));
  311.  
  312.         if((proc = CreateNewProcTags(NP_Entry,asyncmethodfunc,
  313.                                               (tagList) ? TAG_MORE : TAG_IGNORE,tagList,
  314.                                               TAG_DONE)))
  315.         {
  316.             DB(("sending object : %lx, msg : %lx\n",obj,msg));
  317.  
  318.             PutMsg(&proc->pr_MsgPort,&amsg.amm_ExecMessage);
  319.             WaitPort(mport);
  320.         }
  321.  
  322.         DeleteMsgPort(mport);
  323.     }
  324.     return((ULONG) proc);
  325. }
  326. /*FE*/
  327. /*FS*/ ULONG NotifyAttrs(Object * obj, void * ginfo, ULONG flags, ULONG tag1,...)
  328. {
  329.      return(DoMethod(obj, OM_NOTIFY, &tag1, ginfo, flags));
  330. }
  331. /*FE*/
  332.  
  333. /*FS*/ ULONG getstring(Class *cl,Object *obj,struct dttGetString *msg)
  334. {
  335.     struct MyTextDTData *data = INST_DATA(cl,obj);
  336.     struct ClassData *cd = (struct ClassData *) cl->cl_UserData;
  337.     struct GadgetInfo *ginfo = &msg->dttgs_GInfo;
  338.     struct Library *ReqToolsBase;
  339.     ULONG retval = 0;
  340.  
  341.     DB(("before getstring() !\n"));
  342.  
  343.     if((ReqToolsBase = OpenLibrary("reqtools.library",38)))
  344.     {
  345.         retval = rtGetString(data->Buffer,sizeof(data->Buffer),
  346.                                     "Text Datatype Search String",NULL,
  347.                                     RT_Window     ,ginfo->gi_Window,
  348.                                     RT_ReqPos     ,REQPOS_CENTERWIN,
  349.                                     RT_LockWindow ,TRUE,
  350.                                     TAG_DONE);
  351.  
  352.         CloseLibrary(ReqToolsBase);
  353.  
  354.         if(retval)
  355.         {
  356.             Forbid();
  357.             DoMethod(obj,msg->dttgs_SearchMethod,ginfo,data->Buffer,strlen(data->Buffer));
  358.             Permit();
  359.         }
  360.     }
  361.  
  362.     return(retval);
  363. }
  364. /*FE*/
  365. /*FS*/ LONG strseg(struct Line *line,STRPTR str,LONG slen)
  366. {
  367.     STRPTR text = line->ln_Text;
  368.     STRPTR ptr;
  369.     LONG llen = line->ln_TextLen;
  370.     LONG len;
  371.  
  372.     D({UBYTE dbbuf[256];
  373.         strncpy(dbbuf,line->ln_Text,line->ln_TextLen);
  374.         dbbuf[line->ln_TextLen] ='\0';
  375.         bug("%s\n",dbbuf);
  376.       });
  377.  
  378.     while(llen >= slen)
  379.     {
  380.         ptr = str;
  381.         len = slen;
  382.  
  383.         while(*text == *ptr)
  384.         {
  385.             text++;
  386.             ptr++;
  387.             llen--;
  388.             len--;
  389.         }
  390.  
  391.         if(len==0)
  392.             return(1);
  393.         else
  394.         {
  395.             text++;
  396.             llen--;
  397.         }
  398.     }
  399.     return(0);
  400. }
  401. /*FE*/
  402. /*FS*/ ULONG searchstring(Class *cl,Object *obj,LONG direction,struct dttSearchText *msg)
  403. {
  404.     struct ClassData *cd = (struct ClassData *) cl->cl_UserData;
  405.     struct MyTextDTData *data = INST_DATA(cl,obj);
  406.  
  407.     struct List *list;
  408.  
  409.     DB(("search for : \"%s\" !\n",msg->dttst_Text));
  410.  
  411.     if(GetAttr(TDTA_LineList,obj,(ULONG *) &list))
  412.     {
  413.         struct Line *line;
  414.         LONG len = msg->dttst_TextLen;
  415.         LONG found = data->FoundLine;
  416.         LONG y = 0;
  417.  
  418.         line = (struct Line *) list->lh_Head;
  419.  
  420.         if(direction == -1)
  421.             found--;
  422.  
  423.         while(y <= found && line->ln_Link.mln_Succ)
  424.         {
  425.             if(line->ln_Flags & LNF_LF)
  426.                 y++;
  427.             line = (struct Line *) line->ln_Link.mln_Succ;
  428.         }
  429.  
  430.         found = -1;
  431.  
  432.         if(direction == -1)
  433.         {
  434.             if(line->ln_Link.mln_Pred)
  435.                 line = (struct Line *) line->ln_Link.mln_Pred;
  436.  
  437.             while(line->ln_Link.mln_Pred && found == -1)
  438.             {
  439.                 if(line->ln_Flags & LNF_LF)
  440.                     y--;
  441.  
  442.                 if(line->ln_TextLen >= len)
  443.                 {
  444.                     if(strseg(line,msg->dttst_Text,msg->dttst_TextLen))
  445.                     {
  446.                         found = y;
  447.                         break;
  448.                     }
  449.                 }
  450.                 line = (struct Line *) line->ln_Link.mln_Pred;
  451.             }
  452.         } else
  453.         {
  454.             while(line->ln_Link.mln_Succ && found == -1)
  455.             {
  456.                 if(line->ln_TextLen >= len)
  457.                 {
  458.                     if(strseg(line,msg->dttst_Text,msg->dttst_TextLen))
  459.                     {
  460.                         found = y;
  461.                         break;
  462.                     }
  463.                 }
  464.                 if(line->ln_Flags & LNF_LF)
  465.                     y++;
  466.                 line = (struct Line *) line->ln_Link.mln_Succ;
  467.             }
  468.         }
  469.  
  470.         data->FoundLine = found;
  471.  
  472.         if(found < 0)
  473.         {
  474.             DisplayBeep(msg->dttst_GInfo->gi_Screen);
  475.             found = 0;
  476.         }
  477.         NotifyAttrs(obj,msg->dttst_GInfo,0,DTA_TopVert,found,TAG_DONE);
  478.     }
  479.     return(0);
  480. }
  481. /*FE*/
  482.  
  483. /*FS*/ RegCall GetA4 ULONG mytextdtdispatcher(REGA0 Class *cl,REGA2 Object *obj,REGA1 Msg msg)
  484. {
  485.     struct MyTextDTData *data = INST_DATA(cl,obj);
  486.     ULONG retval = 0;
  487.  
  488.     switch(msg->MethodID)
  489.     {
  490.     case OM_NEW:
  491.         {
  492.             Object *newobj;
  493.  
  494.             if((newobj = (Object *) DoSuperMethodA(cl,obj,msg)))
  495.             {
  496.                 data = INST_DATA(cl,newobj);
  497.  
  498.                 data->FoundLine = -1;
  499.  
  500.                 DB(("new text.datatype object : %lx\n",newobj));
  501.  
  502.                 retval = (ULONG) newobj;
  503.             }
  504.         }
  505.         break;
  506.     case DTM_TRIGGER:
  507.         {
  508.             ULONG searchmethod = DTTM_SEARCHNEXT;
  509.  
  510.             switch(TRG(msg)->dtt_Function)
  511.             {
  512.             case STM_PREV_FIELD:
  513.             case STM_BROWSE_PREV:
  514.                 searchmethod = DTTM_SEARCHPREV;
  515.             case STM_NEXT_FIELD:
  516.             case STM_BROWSE_NEXT:
  517.                 if(data->Buffer[0])
  518.                 {
  519.                     DoMethod(obj,searchmethod,TRG(msg)->dtt_GInfo,data->Buffer,strlen(data->Buffer));
  520.                     break;
  521.                 }
  522.             case STM_ACTIVATE_FIELD:
  523.  
  524.                 data->Msg.MethodID           = DTTM_GETSTRING;
  525.                 /* copy the full GadgetInfo, because this request is asyncron and datatypes
  526.                  * creates this structure on the stack (Oh No) !
  527.                  */
  528.                 data->Msg.dttgs_GInfo        = *TRG(msg)->dtt_GInfo;
  529.                 data->Msg.dttgs_SearchMethod = searchmethod;
  530.  
  531.                 DB(("before async method !\n"));
  532.  
  533.                 DoAsyncMethod(cl,obj,(Msg) &data->Msg,NP_Name,"text.datatype getstring process",TAG_DONE);
  534.                 break;
  535.             }
  536.         }
  537.         break;
  538.     case DTTM_GETSTRING:
  539.         retval = getstring(cl,obj,(struct dttGetString *) msg);
  540.         break;
  541.     case DTTM_SEARCHNEXT:
  542.         retval = searchstring(cl,obj,1,(struct dttSearchText *) msg);
  543.         break;
  544.     case DTTM_SEARCHPREV:
  545.         retval = searchstring(cl,obj,-1,(struct dttSearchText *) msg);
  546.         break;
  547.     default:
  548.         retval = DoSuperMethodA(cl,obj,msg);
  549.     }
  550.  
  551.     return(retval);
  552. }
  553. /*FE*/
  554.  
  555.